# -*- coding:utf-8 -*-
import multiprocessing
import time
import redis
import json
import argparse
import os
import re

import sys
import datetime
import json
import devregister
root_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(root_path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ElevatorAdmin.settings")
import django
django.setup()
from manufacturer.models import AuthorityCode, StatusMsg, AlarmMsg
from utils.logger import get_logger
from manufacturer.call_interface import device_status

PROCESS_NUM = 16
LIST_NAME = 'status'
STOP_FLAG = '.sync_stop'
LOG_FILE = 'sync.log'

logger = get_logger("data-sync")


def func():
    sub_run = True
    r = redis.Redis(host='localhost', port=6379, db=2)
    while sub_run:
        try:
            data = None
            pn = multiprocessing.current_process().name
            logger.info('===%s===' % multiprocessing.current_process().name)
            logger.info('[%s] queue len: %d' % (pn, r.llen(LIST_NAME)))
            ret = r.brpop(LIST_NAME, 5)
            if ret is None:
                if os.path.exists(STOP_FLAG):
                    logger.info('@@@stop')
                    sub_run = False
                continue
            data = json.loads(ret[1])
            logger.info(data)

            error = False
            t = data.get('type', None)
            authority_code = AuthorityCode.objects.filter_active(code=data.get('key')).first()
            logger.info("updateTime ")
            update_time = datetime.datetime.strptime(data.get('time'), '%Y-%m-%d %H:%M:%S')
            logger.info("--over---")
            if not authority_code:
                # redis里面存储了鉴权码但mysql里面没有，数据不同步
                logger.error(u'鉴权码数据不同步：%s' % data.get('key'))
                continue
            if t == 'login':
                # 获取的信息是登陆类型，做判断，如果因为阻塞导致此消息过期，pass掉，否则改为在线状态
                if authority_code.update_time > update_time:
                    logger.info(u'登陆信息已经过时 pass掉')
                    continue
                authority_code.is_online = True
                authority_code.login_time = int(time.time())
                authority_code.save()
                try:
                    device_status.delay(data.get('key'), datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
                except:
                    pass
            elif t == 'status':
                # 判断消息是否过期，过期则抛掉
                status = StatusMsg.objects.filter_active(authority_code=authority_code).first()
                if status and status.update_time > update_time:
                    logger.info(u'状态信息已经过时 pass掉')
                    continue
                else:
                    logger.info(u"开始更新status")
                    devregister.status_update(bin(data.get('value')), bin(data.get('value2')), authority_code.id,
                                              data.get('floor'), data.get('run_times'))
                    logger.info(u'数据有效，更新status')

            elif t == 'alarm':
                # 报警信息全部存储
                devregister.alarm_create(bin(data.get('value')), bin(data.get('value2')), authority_code)
            elif t == 'logout':
                if authority_code.update_time > update_time:
                    logger.info(u'登陆信息已经过时 pass掉')
                    continue
                authority_code.is_online = False
                authority_code.login_time = 0
                status_msg = authority_code.status_msg.all().first()
                # status_msg = StatusMsg.objects.get(sid)
                if status_msg and status_msg.is_stopped == 0:
                    if authority_code.start_work_time:
                        d_time = int(time.time()) - authority_code.start_work_time  # 电梯下线时 认为电梯停止 和 电梯停止时 取运行时间
                        authority_code.up_time += d_time
                    authority_code.start_work_time = 0
                    logger.info(status_msg.id)
                    status_msg.is_stopped = 1
                    status_msg.save()
                authority_code.save()
                try:
                    device_status.delay(data.get('key'), datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
                except:
                    pass

        except KeyboardInterrupt:
            sub_run = False
            logger.info('@@@@@@stop by KeyboardInterrupt')
            error = True
        except Exception as e:
            logger.info(e)
            error = True
        if error:
            if data:
                r.lpush(LIST_NAME, json.dumps(data))
                logger.error('<<<<push data back')
                logger.error(json.dumps(data))
            else:
                logger.error('<<< no data to push back')

        if os.path.exists(STOP_FLAG):
            sub_run = False
            logger.info('@@@@@@stop')


def is_sync_running(c):
    ps = os.popen('ps -ef | grep "python data-sync.py" | grep -v grep | grep -v %s' % c).read().split('\n')
    if len(ps) > 1:
        return True
    else:
        return False


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-action', type=str, choices=['start', 'stop', 'status'], required=False, default='start',
                        help='start or stop sync service')
    parser.add_argument('-process', type=int, required=False, default=1, help='process number, default to 1')
    args = parser.parse_args()
    # time.sleep(20)
    if args.action == 'start':
        if is_sync_running(args.action):
            print 'already running, stop it before start a new sync'
        else:
            print 'start sync'
            if os.path.exists(STOP_FLAG):
                os.remove(STOP_FLAG)
            run = True
            while run:
                pool = multiprocessing.Pool(processes=args.process)
                for i in xrange(args.process):
                    pool.apply_async(func)
                pool.close()
                pool.join()
                if os.path.exists(STOP_FLAG):
                    run = False
                    print '!!!!stop'
                    os.remove(STOP_FLAG)
                    # while True:
    elif args.action == 'stop':
        if not is_sync_running(args.action):
            print 'not running'
        else:
            if not os.path.exists(STOP_FLAG):
                os.mknod(STOP_FLAG)
            print 'signalled stop, check it by "status" argument'
    elif args.action == 'status':
        if is_sync_running(args.action):
            print 'sync running'
        else:
            print 'not running'
